package com.my.adminservice.map.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.github.benmanes.caffeine.cache.Cache;
import com.my.adminapi.map.domin.dto.LocationSearchReqDTO;
import com.my.adminapi.map.domin.dto.PlaceSearchReqDTO;
import com.my.adminapi.map.mapconstants.Constants;
import com.my.adminservice.config.service.ISysArgumentService;
import com.my.adminservice.map.domain.dto.*;
import com.my.adminservice.map.domain.entity.SysRegion;
import com.my.adminservice.map.mapper.RegionMapper;
import com.my.adminservice.map.service.IMapProvider;
import com.my.adminservice.map.service.IMapService;

import com.my.mycommoncore.domain.dto.BasePageDTO;
import com.my.mycommoncore.utils.BeanCopyUtils;
import com.my.mycommoncore.utils.PageUtil;
import com.my.mycommondomain.domian.ResultCode;
import com.my.mycommondomain.exception.ServiceException;
import com.my.mycommonredis.service.RedisService;
import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import utils.CacheUtil;


import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;


@Service
public class MapServiceImpl implements IMapService {
    private static final Logger log = LoggerFactory.getLogger(MapServiceImpl.class);
    @Autowired
    private RegionMapper regionMapper;
    @Autowired
    private RedisService redisService;
    @Autowired
    private Cache<String,Object> caffeineCache;
    @Autowired
    private IMapProvider mapProvider;
    @Autowired
    private ISysArgumentService sysArgumentService;
    @Override
    public List<SysRegionDTO> getCityList() {
        List<SysRegionDTO> cacheCityList = CacheUtil.getCache(Constants.CITY_LIST, caffeineCache, new TypeReference<List<SysRegionDTO>>() {
        }, redisService);
        return cacheCityList;

    }

    @Override
    public Map<String, List<SysRegionDTO>> getCityListPinyin() {
        Map<String, List<SysRegionDTO>> cacheCityListPinyin = CacheUtil.getCache(Constants.CACHE_MAP_CITY_PINYIN_KEY, caffeineCache, new TypeReference<Map<String, List<SysRegionDTO>>>() {
        }, redisService);
        return cacheCityListPinyin;
    }

    @Override
    public List<SysRegionDTO> getChildrenList(Long parentId) {
        //先查缓存,缓存不存在,查数据库
        List<SysRegionDTO> cache = CacheUtil.getCache(Constants.CACHE_MAP_CITY_CHILDREN_KEY+parentId, caffeineCache, new TypeReference<List<SysRegionDTO>>() {
        }, redisService);
        if(cache!=null){
            return cache;
        }
        //缓存不存在查数据库
        List<SysRegion> sysRegions = regionMapper.selectAllRegion();
        List<SysRegionDTO> sysRegionDTOList = new ArrayList<>();
        for (SysRegion sysRegion : sysRegions) {
            if(sysRegion.getParentId()!=null&&sysRegion.getParentId().equals(parentId)){
                SysRegionDTO sysRegionDTO = new SysRegionDTO();
                BeanCopyUtils.copyProperties(sysRegion, sysRegionDTO);
                sysRegionDTOList.add(sysRegionDTO);
            }
        }
        //设置缓存
        CacheUtil.setCache(Constants.CACHE_MAP_CITY_CHILDREN_KEY+parentId,caffeineCache,sysRegionDTOList,redisService,120L, TimeUnit.MINUTES);

        return sysRegionDTOList;
    }

    @Override
    public List<SysRegionDTO> getHostCityList() {
        List<SysRegionDTO> sysRegionDTOList=new ArrayList<>();
        //先查缓存
        List<SysRegionDTO> cache = CacheUtil.getCache(Constants.CACHE_MAP_CITY_HOST_KEY, caffeineCache, new TypeReference<List<SysRegionDTO>>() {
        }, redisService);
        if(cache!=null){
            return cache;
        }
        //缓存中没有查数据库
        String ids=sysArgumentService.getByConfigKey(Constants.HOT_CITY_KET).getValue();
        List<Long> idList=new ArrayList<>();
        for(String id:ids.split(",")){
            idList.add(Long.parseLong(id));
        }
        List<SysRegion> sysRegions = regionMapper.selectBatchIds(idList);
        for (SysRegion sysRegion : sysRegions) {
            SysRegionDTO sysRegionDTO = new SysRegionDTO();
            BeanCopyUtils.copyProperties(sysRegion, sysRegionDTO);
            sysRegionDTOList.add(sysRegionDTO);
        }
        //设置缓存
        CacheUtil.setCache(Constants.CACHE_MAP_CITY_HOST_KEY,caffeineCache,sysRegions,redisService,120L, TimeUnit.MINUTES);
        return sysRegionDTOList;
    }

    @Override
    public BasePageDTO<SearchPoiDTO> getSearchMapList(PlaceSearchReqDTO placeSearchReqDTO) {
        //构建腾讯位置服务的入参
        SuggestSearchDTO suggestSearchDTO = new SuggestSearchDTO();
        BeanCopyUtils.copyProperties(placeSearchReqDTO, suggestSearchDTO);
        suggestSearchDTO.setId(String.valueOf(placeSearchReqDTO.getId()));
        suggestSearchDTO.setPageIndex(placeSearchReqDTO.getPageNo());
        //调取地图服务
        PoiListDTO poiListDTO = mapProvider.searchQQMapPlaceByRegion(suggestSearchDTO);
        //做对象结果转换
        List<PoiDTO> poiDTOList = poiListDTO.getData();
        BasePageDTO<SearchPoiDTO> result=new BasePageDTO<>();
        result.setTotals(poiListDTO.getCount());
        result.setTotalPages(PageUtil.getTotalPages(poiListDTO.getCount(),placeSearchReqDTO.getPageSize()));
        List<SearchPoiDTO> pageRes = new ArrayList<>();
        for (PoiDTO poiDTO : poiDTOList) {
            SearchPoiDTO searchPoiDTO = new SearchPoiDTO();
            BeanUtils.copyProperties(poiDTO, searchPoiDTO);
            searchPoiDTO.setLongitude(poiDTO.getLocation().getLng());
            searchPoiDTO.setLatitude(poiDTO.getLocation().getLat());
            pageRes.add(searchPoiDTO);
        }
        result.setList(pageRes);
        return result;
    }

    @Override
    public RegionCityDTO getCityByLocation(LocationSearchReqDTO locationSearchReqDTO) {
        //构造腾讯地图请求入参
        LocationDTO locationDTO=new LocationDTO();
        BeanUtils.copyProperties(locationSearchReqDTO, locationDTO);
        RegionCityDTO regionCityDTO=new RegionCityDTO();
        //调用腾讯地图服务
        GeoResultDTO qqMapDistrictByLonLat = mapProvider.getQQMapDistrictByLonLat(locationDTO);
        if(qqMapDistrictByLonLat!=null&& qqMapDistrictByLonLat.getResult()!=null && qqMapDistrictByLonLat.getResult().getAd_info()!=null){
            String name = qqMapDistrictByLonLat.getResult().getAd_info().getCity();
            List<SysRegionDTO> cache = CacheUtil.getCache(Constants.CITY_LIST, caffeineCache, new TypeReference<List<SysRegionDTO>>() {
            }, redisService);
            if(cache!=null){
                for (SysRegionDTO sysRegionDTO: cache){
                    if(name.equals(sysRegionDTO.getFullName())){
                        BeanCopyUtils.copyProperties(sysRegionDTO,regionCityDTO);
                        return regionCityDTO;
                    }
                }
            }else {
                log.error("查询不到该经纬度的城市:{}",qqMapDistrictByLonLat);
                throw new ServiceException(ResultCode.INVALID_PARA);
            }
        }

        return regionCityDTO;
    }

    @PostConstruct
    public void initCityMap(){
        List<SysRegion> sysRegions = regionMapper.selectAllRegion();
        //加载城市列表缓存
        loadCityInfo(sysRegions);
        //加载城市分类列表缓存
        loadCityPinyinList(sysRegions);
    }
    public void loadCityInfo(List<SysRegion> sysRegions){
        List<SysRegionDTO> sysRegionDTOList=new ArrayList<SysRegionDTO>();
        for (SysRegion sysRegion : sysRegions) {
            if(sysRegion.getLevel().equals(Constants.CITY_LEVEL)){
                SysRegionDTO sysRegionDTO=new SysRegionDTO();
                BeanCopyUtils.copyProperties(sysRegion,sysRegionDTO);
                sysRegionDTOList.add(sysRegionDTO);
            }
        }
        CacheUtil.setCache(Constants.CITY_LIST,caffeineCache,sysRegionDTOList,redisService,120L, TimeUnit.MINUTES);
    }
    public void loadCityPinyinList(List<SysRegion> sysRegions){
        Map<String,List<SysRegionDTO>> map=new TreeMap<>();
        for(SysRegion sysRegion : sysRegions){
            if(sysRegion.getLevel().equals(Constants.CITY_LEVEL)){
                SysRegionDTO sysRegionDTO=new SysRegionDTO();
                BeanCopyUtils.copyProperties(sysRegion,sysRegionDTO);
                String substring = sysRegionDTO.getPinyin().toUpperCase().substring(0, 1);
                //判断首字母是否在map中
                if(map.containsKey(substring)){
                    map.get(substring).add(sysRegionDTO);
                }else {
                    List<SysRegionDTO> list=new ArrayList<>();
                    list.add(sysRegionDTO);
                    map.put(substring,list);
                }
            }
        }
        //构建缓存
        CacheUtil.setCache(Constants.CACHE_MAP_CITY_PINYIN_KEY,caffeineCache,map,redisService,120L, TimeUnit.MINUTES);

    }
}
